package com.game.message.connetion;

import com.game.message.Msg;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.buffer.UnpooledHeapByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
import io.netty.util.AttributeKey;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 长连接管理器
 *
 * @author lizhiwei
 * @createAt Feb 17, 2015
 */
public class ConnectionManager {
    public static AttributeKey userIdAttributeKey = AttributeKey.newInstance("userId");
    public static AttributeKey gameIdAttributeKey = AttributeKey.newInstance("gameId");
    public static AttributeKey connectTypeAttributeKey = AttributeKey.newInstance("connectType");
    private static ConnectionManager mInstance = null;

    private final Map<Integer, ChannelHandlerContext> playerClientCtxMap;

    private ConnectionManager() {
        playerClientCtxMap = new ConcurrentHashMap<Integer, ChannelHandlerContext>();
    }

    public static ConnectionManager getInstance() {
        if (mInstance == null) {
            mInstance = new ConnectionManager();
        }
        return mInstance;
    }

    public ChannelHandlerContext create(ChannelHandlerContext playerClientCtx, int userId, int gameId) {
        playerClientCtxMap.put(userId, playerClientCtx);
        // put id to channel
        playerClientCtx.attr(userIdAttributeKey).set(userId);
        playerClientCtx.attr(gameIdAttributeKey).set(gameId);
        return playerClientCtx;
    }

    public void remove(ChannelHandlerContext playerClientCtx) {
        Object o = playerClientCtx.attr(userIdAttributeKey).get();
        playerClientCtxMap.remove(o);
    }

    public ChannelHandlerContext get(int userId) {
        return playerClientCtxMap.get(userId);
    }

    public void writeMessage(int userId, Msg message) {
        ChannelHandlerContext channelHandlerContext = get(userId);
        boolean b = channelHandlerContext.attr(connectTypeAttributeKey).get() != null;
        if (b) {
            ByteBuf result = Unpooled.buffer(message.getLength() + Msg.headLength);
            result.writeInt(message.getLength());
            result.writeInt(message.getMsgId());
            result.writeBytes(message.getBody());
            WebSocketFrame webSocketFrame = new BinaryWebSocketFrame(result);
            channelHandlerContext.writeAndFlush(webSocketFrame);
        } else {
            channelHandlerContext.writeAndFlush(message);
        }
    }

    public void writeMessage(ChannelHandlerContext ctx, Msg message) {
        ctx.writeAndFlush(message);
    }

    /**
     * mark
     * 不要使用Map里面的size()，每次获取都需要计算
     *
     * @return
     */
    public int count() {
        return playerClientCtxMap.size();
    }
}
